﻿
// ClientView.cpp: CClientView 类的实现
//

#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "Client.h"
#endif

#include "ClientDoc.h"
#include "ClientView.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CClientView

IMPLEMENT_DYNCREATE(CClientView, CView)

BEGIN_MESSAGE_MAP(CClientView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
    ON_COMMAND(ID_OBJECT_INSERT, &CClientView::OnInsertObject)
END_MESSAGE_MAP()

// CClientView 构造/析构

CClientView::CClientView() noexcept
{
    m_lpIOleObject = nullptr;
    m_lpIStorage = nullptr;
    m_lpIViewObject = nullptr;
    m_lpIAdviseSink = nullptr;
}

CClientView::~CClientView()
{
}

BOOL CClientView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CClientView 绘图

void CClientView::OnDraw(CDC* pDC)
{
    CClientDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    HDC hDC = pDC->m_hDC;
    RECTL rc;

    if (m_lpIViewObject)
    {
        rc.left = 0;
        rc.top = 0;
        rc.right = 100;
        rc.bottom = 100;

        m_lpIViewObject->Draw(DVASPECT_CONTENT, -1, nullptr, nullptr, hDC, hDC, 
            &rc, nullptr, nullptr, 0);
    }
}


// CClientView 打印

BOOL CClientView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CClientView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CClientView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CClientView 诊断

#ifdef _DEBUG
void CClientView::AssertValid() const
{
	CView::AssertValid();
}

void CClientView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CClientDoc* CClientView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClientDoc)));
	return (CClientDoc*)m_pDocument;
}
#endif //_DEBUG


// CClientView 消息处理程序

void CClientView::OnInsertObject()
{
    COleInsertDialog OleInsertDlg;
    HRESULT hResult;
    IOleObject* lpIOleObject = nullptr;
    IStorage* lpIStorage = nullptr;
    IOleClientSite* lpIOleClientSite = nullptr;
    IViewObject* lpIViewObject = nullptr;
    IAdviseSink* lpIAdviseSink = nullptr;
    CClientDoc* lpClientDoc = GetDocument();
    BOOL bSuccess = FALSE;
    RECTL rc;
    HDC hDC;

    if (IDOK != OleInsertDlg.DoModal()) return;

    do
    {
        //
        //  获取IOleClientSite接口指针
        //

        lpIOleClientSite = lpClientDoc->GetClientSite();
        if (!lpIOleClientSite) break;

        //
        //  创建存储对象
        //

        if (!m_lpIStorage)
        {
            hResult = StgCreateStorageEx(L".\\FILE.BIN", STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
                STGFMT_STORAGE, 0, nullptr, nullptr, IID_IStorage, (void**)&lpIStorage);
            if (S_OK != hResult || !lpIStorage) break;
            m_lpIStorage = lpIStorage;
        }

        //
        //  通过CLSID创建嵌入对象
        //

        if (!m_lpIOleObject)
        {
            hResult = OleCreate(OleInsertDlg.m_io.clsid, IID_IOleObject, 1, nullptr, 
                nullptr, m_lpIStorage, (void**)&lpIOleObject);
            if (S_OK != hResult || !lpIOleObject) break;

            hResult = lpIOleObject->SetClientSite(lpIOleClientSite);
            if (S_OK != hResult) break;

            m_lpIOleObject = lpIOleObject;
        }
        else
        {
            AfxMessageBox(_T("只允许插入一个对象"));
            break;
        }

        //
        //  响应用户操作
        //

        hResult = lpIOleObject->DoVerb(0, nullptr, lpIOleClientSite, 0,
            GetSafeHwnd(), CRect(0, 0, 100, 100));
        if (S_OK != hResult) break;

        //
        //  获取IViewObject接口指针
        //

        hResult = lpIOleObject->QueryInterface(IID_IViewObject, (void**)&lpIViewObject);
        if (S_OK != hResult) break;
        m_lpIViewObject = lpIViewObject;

        //
        //  获取IAdviseSink接口指针
        //

        lpIAdviseSink = lpClientDoc->GetAdviseSink();
        lpIViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpIAdviseSink);
        m_lpIAdviseSink = lpIAdviseSink;

        //
        //  绘制
        //

        hDC = GetDC()->m_hDC;
        rc.left = 0;
        rc.top = 0;
        rc.right = 100;
        rc.bottom = 100;
        hResult = lpIViewObject->Draw(DVASPECT_CONTENT, -1, nullptr, nullptr, hDC, hDC, &rc, nullptr, nullptr, 0);
        if (S_OK != hResult) break;

        bSuccess = TRUE;

    } while (FALSE);

    if (lpIAdviseSink)
        lpIAdviseSink->Release();

    if (lpIOleClientSite)
        lpIOleClientSite->Release();

    if (!bSuccess)
    {
        if (m_lpIViewObject)
        {
            m_lpIViewObject->SetAdvise(1, 0, nullptr);
            m_lpIViewObject->Release();
            m_lpIViewObject = nullptr;
        }

        if (m_lpIOleObject)
        {
            m_lpIOleObject->Close(1);
            m_lpIOleObject->Release();
            m_lpIOleObject = nullptr;
        }

        if (m_lpIStorage)
        {
            m_lpIStorage->Release();
            m_lpIStorage = nullptr;
        }
    }
}


void CClientView::PostNcDestroy()
{
    if (m_lpIOleObject)
    {
        m_lpIOleObject->Close(1);
        m_lpIOleObject->Release();
    }

    if (m_lpIViewObject)
    {
        m_lpIViewObject->SetAdvise(1, 0, nullptr);
        m_lpIViewObject->Release();
        m_lpIViewObject = nullptr;
    }

    if (m_lpIStorage)
    {
        m_lpIStorage->Release();
        m_lpIStorage = nullptr;
    }

    CView::PostNcDestroy();
}
